package com.sky.aspect;

import com.sky.annotation.AutoFill;
import com.sky.context.BaseContext;
import com.sky.enumeration.OperationType;
import com.sky.utils.ParaVerifUtil;
import lombok.extern.slf4j.Slf4j;
import org.aspectj.lang.JoinPoint;
import org.aspectj.lang.Signature;
import org.aspectj.lang.annotation.Aspect;
import org.aspectj.lang.annotation.Before;
import org.aspectj.lang.annotation.Pointcut;
import org.aspectj.lang.reflect.MethodSignature;
import org.springframework.stereotype.Component;

import java.lang.reflect.Field;
import java.lang.reflect.Method;
import java.time.LocalDateTime;


/*
* 自定义切面类
* */
@Aspect
@Component
@Slf4j
public class AutoFillAspect {
    private static final String CREATE_TIME = "createTime";
    private static final String CREATE_USER = "createUser";
    private static final String UPDATE_TIME = "updateTime";
    private static final String UPDATE_USER = "updateUser";

    /*
    * 切入点
    * */
    @Pointcut("execution(* com.sky.mapper.*.*(..)) && @annotation(com.sky.annotation.AutoFill)")
    public void autoFillPointcut() {}

    /*
    * 前置通知
    * */
    @Before("autoFillPointcut()")
    public void doBefore(JoinPoint joinPoint) throws Throwable {
        log.info("执行方法：{}，参数：{}", joinPoint.getSignature().getName(), joinPoint.getArgs());
        //获取拦截方法 获取签名对象->获取方法的注解对象->获取注解的值   该签名对象包含了被拦截方法的所有信息
        MethodSignature signature = (MethodSignature) joinPoint.getSignature();
        AutoFill annotation = signature.getMethod().getAnnotation(AutoFill.class);
        OperationType operationType = annotation.value();

        //获取被拦截方法的参数对象
        Object arg = joinPoint.getArgs()[0];
        if (ParaVerifUtil.isEmpty(arg)) return;
        //数据准备
        Class<?> clazz = arg.getClass();
        LocalDateTime now = LocalDateTime.now();
        Long LoginId = BaseContext.getCurrentId();
        // 动态检查字段存在性，并设置值
        setFieldIfExists(clazz, arg, UPDATE_TIME, now);
        setFieldIfExists(clazz, arg, UPDATE_USER, LoginId);

        if (operationType == OperationType.INSERT) {
            setFieldIfExists(clazz, arg, CREATE_TIME, now);
            setFieldIfExists(clazz, arg, CREATE_USER, LoginId);
        }
    }

    // 安全设值工具方法
    private void setFieldIfExists(Class<?> clazz, Object obj, String fieldName, Object value) {
        try {
            Field field = clazz.getDeclaredField(fieldName);
            field.setAccessible(true);
            field.set(obj, value);
        } catch (NoSuchFieldException | IllegalAccessException e) {
            // 字段不存在或访问失败时静默跳过
            log.debug("字段 {} 不存在或设值失败: {}", fieldName, e.getMessage());
        }
    }



}
